<?php


namespace App\Services;

use App\DTOS\Admin\CustomerDTO;
use App\Exceptions\ServiceException;
use App\Models\Customer;
use App\Models\Game\OnLine;
use App\Models\Game\SortPet;
use App\Models\Game\SortUser;
use App\Models\Game\UserRole;
use App\Models\Game\BanList;
use App\Models\Game\LoginLogs;
use App\Models\Game\Sale;
use App\Models\Game\LoginNum;
use App\Models\SimulationLogin;
use App\Services\Game\DouyinService;
use App\Services\Game\YiyouService;
use App\Utils\MyLog;
use App\Utils\ResponseUtil;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Nette\Utils\Random;

class CustomerService
{

    private IdentifyService $identifyService;
    private SmsService $smsService;
    private DouyinService $DouyinService;
    private YiyouService $yiyouService;

    /**
     * CustomerService constructor.
     * @param IdentifyService $identifyService
     * @param SmsService $smsService
     * @param DouyinService $DouyinService
     */
    public function __construct(IdentifyService $identifyService,SmsService $smsService,DouyinService $DouyinService,YiyouService $yiyouService)
    {
        $this->identifyService = $identifyService;
        $this->smsService = $smsService;
        $this->DouyinService = $DouyinService;
        $this->yiyouService = $yiyouService;
    }

    /**
     * 榜单TOP查询
     * @param CustomerDTO $customerDTO
     * @return array
     */
    public function gettop(CustomerDTO $customerDTO)
    {
        $type = $customerDTO->getType();
        $page = $customerDTO->getPage();
        $pageSize = $customerDTO->getLimit();
        $ga = $customerDTO->getGameArea();

        // 设置分区库连接
        global $gameArea;
        $gameArea = $ga ?: 0;


        switch ($type) {
            case 'level':
                $query = SortUser::query()
                    ->selectRaw('roleid as role_id, nick, level')
                    ->orderByDesc('level');
                break;
            case 'power':
                $query = SortUser::query()
                    ->selectRaw('roleid as role_id, nick, fight as power')
                    ->orderByDesc('fight');
                break;
            case 'soul':
                $query = SortPet::query()
                    ->selectRaw('role_id as role_id, id as pet_id, score')
                    ->orderByDesc('score');
                $paginator = $query->paginate($pageSize, ['*'], 'page', $page);
                $items = collect($paginator->items());
                $roleIds = $items->pluck('role_id')->unique()->values()->all();
                $petIds = $items->pluck('pet_id')->unique()->values()->all();

                // 获取角色名称
                $roles = UserRole::query()->whereIn('id',$roleIds)->pluck('nick','id');

                // 获取宠物名称
                $pets = \App\Models\Game\PetConfig::query()->whereIn('id',$petIds)->pluck('name','id');

                $mapped = $items->map(function($row) use ($roles, $pets){
                    $row->nick = $roles[$row->role_id] ?? '';
                    $row->pet_name = $pets[$row->pet_id] ?? '';
                    return $row;
                })->values()->all();
                return [
                    'count' => $paginator->total(),
                    'data' => $mapped,
                ];
            case 'enhance_times':
                $query = UserRole::query()
                    ->selectRaw('id as role_id, nick, JSON_UNQUOTE(JSON_EXTRACT(combat, "$\.boost_count")) + 0 as enhance_times')
                    ->orderByDesc('enhance_times');
                break;
            case 'refine_times':
                $query = UserRole::query()
                    ->selectRaw('id as role_id, nick, JSON_UNQUOTE(JSON_EXTRACT(combat, "$\.wash_count")) + 0 as refine_times')
                    ->orderByDesc('refine_times');
                break;
            case 'wash_times':
                $query = UserRole::query()
                    ->selectRaw('id as role_id, nick, JSON_UNQUOTE(JSON_EXTRACT(pet, "$\.total_wash_count")) + 0 as wash_times')
                    ->orderByDesc('wash_times');
                break;
            case 'tower_floor':
                $query = UserRole::query()
                    ->selectRaw('id as role_id, nick, JSON_UNQUOTE(JSON_EXTRACT(daily, "$\\.\\"7\\"")) + 0 as tower_floor')
                    ->orderByDesc('tower_floor');
                break;
            default:
                // 默认返回空
                return ['count' => 0, 'data' => []];
        }

        $paginator = $query->paginate($pageSize, ['*'], 'page', $page);
        return [
            'count' => $paginator->total(),
            'data' => $paginator->items(),
        ];
    }


    /**
     * 游戏进度分布查询
     * @param CustomerDTO $customerDTO
     * @return array
     */
    public function getprogress(CustomerDTO $customerDTO)
    {
        $type = $customerDTO->getType();
        $page = $customerDTO->getPage();
        $pageSize = $customerDTO->getLimit();
        $ga = $customerDTO->getGameArea();

        // 设置分区库连接
        global $gameArea;
        $gameArea = $ga ?: 0;

        switch ($type) {
            case 'level':
                return $this->getLevelDistribution();
            case 'tower':
                return $this->getTowerDistribution();
            case 'task':
                return $this->getTaskDistribution($ga);
            case 'power':
                $query = SortUser::query()
                    ->selectRaw('roleid as role_id, nick, fight as power')
                    ->orderByDesc('fight');
                break;
            default:
                // 默认返回空
                return ['count' => 0, 'data' => []];
        }

        $paginator = $query->paginate($pageSize, ['*'], 'page', $page);
        return [
            'count' => $paginator->total(),
            'data' => $paginator->items(),
        ];
    }

    /**
     * 等级分布统计
     * @return array
     */
    private function getLevelDistribution()
    {
        // 分母：全体角色数
        $totalCount = UserRole::count();
        if ($totalCount == 0) {
            return ['count' => 0, 'data' => []];
        }

        // 先从 sort_user 获取每个等级的人数
        global $gameArea; if (!$gameArea) { $gameArea = 0; }
        $funcConn = DB::connection('function_'.$gameArea);
        $logConn = DB::connection('log_'.$gameArea);

        // 获取各等级人数
        $levelCounts = $funcConn->table('sort_user')
            ->selectRaw('level, COUNT(*) as count')
            ->groupBy('level')
            ->orderBy('level')
            ->get();

        $result = [];
        foreach ($levelCounts as $levelData) {
            $level = $levelData->level;
            $count = $levelData->count;

            // 获取该等级下所有角色的升级日志，计算平均滞留时间
            $roleIds = $funcConn->table('sort_user')
                ->where('level', $level)
                ->pluck('roleid');

            if ($roleIds->isNotEmpty()) {
                if ($level == 1) {
                    // 1级角色：如果没有升级记录，用角色创建时间计算
                    $gameDb = config('database.connections.game_'.$gameArea.'.database');
                    $logoDb = config('database.connections.log_'.$gameArea.'.database');

                    $avgStayTime = DB::connection('function_'.$gameArea)
                        ->table('sort_user as su')
                        ->leftJoin(DB::raw($gameDb.'.user_role_0 as ur'), 'ur.id', '=', 'su.roleid')
                        ->leftJoin(DB::raw($logoDb.'.log_role_upgrade as ru'), function($join) {
                            $join->on('ru.roleId', '=', 'su.roleid')
                                 ->where('ru.new_lv', '=', 1);
                        })
                        ->whereIn('su.roleid', $roleIds)
                        ->selectRaw('ROUND(AVG(TIMESTAMPDIFF(MINUTE,
                            COALESCE(FROM_UNIXTIME(NULLIF(ru.logTime,0)), FROM_UNIXTIME(NULLIF(ur.createtime,0))),
                            NOW()))/1440, 2) as avg_stay_time')
                        ->value('avg_stay_time') ?: 0;
                } else {
                    // 其他等级：用升级日志时间计算
                    $avgStayTime = $logConn->table('log_role_upgrade')
                        ->whereIn('roleId', $roleIds)
                        ->where('new_lv', $level)
                        ->selectRaw('ROUND(AVG(TIMESTAMPDIFF(MINUTE, FROM_UNIXTIME(NULLIF(logTime,0)), NOW()))/1440, 2) as avg_stay_time')
                        ->value('avg_stay_time') ?: 0;
                }
            } else {
                $avgStayTime = 0;
            }

            $result[] = [
                'level' => $level,
                'count' => $count,
                'percentage' => round($count * 100.0 / $totalCount, 2),
                'avg_stay_time' => $avgStayTime
            ];
        }

        return [
            'count' => count($result),
            'data' => $result,
            'total_count' => $totalCount
        ];
    }

    /**
     * 爬塔分布统计
     * @return array
     */
    private function getTowerDistribution()
    {
        // 分母切换为整个角色表人数
        $totalCount = UserRole::count();

        if ($totalCount == 0) {
            return ['count' => 0, 'data' => []];
        }

        // 直接从 game_{ga}.user_role_0 的 daily[7] 读取爬塔层数，升序排序
        global $gameArea; if (!$gameArea) { $gameArea = 0; }
        $gameConn = DB::connection('game_'.$gameArea);
        // 提取 daily->"7" 层数，并安全转为无符号整数（不存在/非数字时为 0）
        $floorExpr = "CAST(COALESCE(JSON_UNQUOTE(JSON_EXTRACT(ur.copyData, '$.\"1\"')), '0') AS UNSIGNED)";
        $towerStats = $gameConn->table('user_role_0 as ur')
            ->selectRaw($floorExpr.' as tower_level, COUNT(*) as count, ROUND(COUNT(*) * 100.0 / ?, 2) as percentage, ROUND(AVG(TIMESTAMPDIFF(MINUTE, FROM_UNIXTIME(NULLIF(ur.createtime,0)), NOW()))/1440, 2) as avg_stay_time', [$totalCount])
            ->groupByRaw($floorExpr)
            ->orderBy('tower_level', 'asc')
            ->get();

        return [
            'count' => $towerStats->count(),
            'data' => $towerStats->toArray(),
            'total_count' => $totalCount
        ];
    }

    /**
     * 主线任务分布统计
     * @return array
     */
    private function getTaskDistribution($ga)
    {
        // 基于任务日志统计主线任务（task_type=1）：
        // - 已接未完成：存在 action_type=0 且不存在 action_type=1
        // - 已提交已完成：存在 action_type=0 且存在 action_type=1
        // 平均滞留时间：首次接任务到提交时间；未提交则到当前时间（单位：天）
        $logConn = DB::connection('log_'.$ga);
        MyLog::info('服务器ID'.json_encode($ga));
        // 使用原生SQL查询，避免复杂的子查询构建
        $sql = "
            SELECT
                t.task_id,
                SUM(CASE WHEN t.accept_count > 0 AND t.submit_count = 0 THEN 1 ELSE 0 END) AS accept_unfinished,
                SUM(CASE WHEN t.accept_count > 0 AND t.submit_count > 0 THEN 1 ELSE 0 END) AS completed,
                ROUND(AVG(TIMESTAMPDIFF(MINUTE, FROM_UNIXTIME(NULLIF(t.accept_ts,0)), IFNULL(FROM_UNIXTIME(NULLIF(t.submit_ts,0)), NOW())))/1440, 2) AS avg_stay_time
            FROM (
                SELECT
                    lt.roleId,
                    lt.task_id,
                    MIN(CASE WHEN lt.action_type = 0 THEN lt.logTime END) AS accept_ts,
                    MIN(CASE WHEN lt.action_type = 1 THEN lt.logTime END) AS submit_ts,
                    SUM(CASE WHEN lt.action_type = 0 THEN 1 ELSE 0 END) AS accept_count,
                    SUM(CASE WHEN lt.action_type = 1 THEN 1 ELSE 0 END) AS submit_count
                FROM log_role_task lt
                WHERE lt.task_type = 1
                GROUP BY lt.roleId, lt.task_id
            ) t
            GROUP BY t.task_id
            ORDER BY t.task_id
        ";

        $taskStats = $logConn->select($sql);
        // 任务名称映射
        $taskNames = \App\Models\Game\Task::query()->pluck('name', 'id');
        // 分母：全体角色数
        $totalCount = UserRole::count();
        $data = collect($taskStats)->map(function($row) use ($taskNames){
            return [
                'task_id' => (int)$row->task_id,
                'task_name' => (string)($taskNames[$row->task_id] ?? ''),
                'accept_unfinished' => (int)$row->accept_unfinished,
                'completed' => (int)$row->completed,
                'avg_stay_time' => (float)$row->avg_stay_time,
            ];
        })->values()->all();

        // 增加占比字段（占总角色人数）
        if ($totalCount > 0) {
            foreach ($data as &$item) {
                $item['accept_unfinished_percent'] = round($item['accept_unfinished'] * 100.0 / $totalCount, 2);
                $item['completed_percent'] = round($item['completed'] * 100.0 / $totalCount, 2);
            }
            unset($item);
        } else {
            foreach ($data as &$item) {
                $item['accept_unfinished_percent'] = 0.0;
                $item['completed_percent'] = 0.0;
            }
            unset($item);
        }

        return [
            'count' => count($data),
            'data' => $data,
        ];
    }

    /**
     * @param CustomerDTO $customerDTO
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    public function paginate(CustomerDTO $customerDTO){

        $customerIds = $customerDTO->getCustomerIds();//角色列表
        $phones = $customerDTO->getPhones();//角色列表
        $phone = $customerDTO->getPhone();
        $realName = $customerDTO->getRealName();
        $page = $customerDTO->getPage();
        $channel_uuid = $customerDTO->getChannelUuid();
        $pageSize = $customerDTO->getLimit();
        $invite_code = $customerDTO->getInviteCode();
        $channelType = $customerDTO->getChannelType();
        $customerId = $customerDTO->getCustomerId();
        $mobile = $customerDTO->getMobile();
        $gamechannel = $customerDTO->getGamechannel();

        $model = Customer::query();

        if ($customerId){
            $model->where('id',$customerId);
        }
        if ($channel_uuid){
            $channel_uuids = explode("\n",$channel_uuid);

            $model->whereIn('channel_uuid',$channel_uuids);
        }
        if ($channelType){
            $model->where('channel_type',$channelType);
        }
        if ($gamechannel){
            $model->where('channel_type',$gamechannel);
        }
        if ($phone) {
            $model->where('phone','like','%'.$phone.'%');
        }
        if ($mobile) {
            $model->where('mobile','like','%'.$mobile.'%');
        }
        if ($realName) {
            $model->where('real_name','like','%'.$realName.'%');
        }
        if ($invite_code){
            $model->where('invite_code',$invite_code);
        }
        if ($customerIds){
            $customerIdlists = explode("\n",$customerIds);
                $model->whereIn('id',$customerIdlists);
        }
        if ($phones){
            $phoneids = explode("\n",$phones);
            $model->whereIn('phone',$phoneids);
        }
        return $model->orderByDesc('id')->paginate($pageSize,'*','page',$page);
    }

    public function register(CustomerDTO $customerDTO)
    {
        DB::beginTransaction();
        try {
            $insert = [];
            $phone = $customerDTO->getPhone();
            $password = $customerDTO->getPassword();
            if (!preg_match("/^[a-zA-Z0-9]+$/",$password)){
                throw new ServiceException('密码仅支持数字和字母');
            }
            $realName = $customerDTO->getRealName();
            $inviteCode = strtoupper($customerDTO->getInviteCode());
            $identityCode = strtoupper($customerDTO->getIdentityCode());
            $packageNo = $customerDTO->getPackageNo();
            if ($packageNo){
                $insert['package_no'] = $packageNo;
            }
            $insert['phone'] = $phone;
            $insert['password'] = Crypt::encryptString($password);
            $insert['real_name'] = $customerDTO->getRealName();
            $insert['identity_code'] = $identityCode;
            $insert['updated_at'] = $insert['created_at'] = now();

            $messageCode = $customerDTO->getMessageCode();
            if (!isPhone($phone)){
                throw new ServiceException('注册失败,手机号格式错误');
            }
            //验证验证码
            if ($messageCode != Redis::get('registerCode_'.$phone)){
                throw new ServiceException('验证码错误');
            }
            if (Customer::query()->where('identity_code',$identityCode)->count() >= 5){
                throw new ServiceException('此身份证已注册了5个账号');
            }
            if (Customer::query()->where('phone',$phone)->exists()){
                throw new ServiceException('此账号已经存在');
            }
            if (calculateAgeByIDCard($identityCode)<16){
                throw new ServiceException('身份证小于16岁');
            }
            if (!$this->identifyService->verify2($realName,$identityCode)){
                throw new ServiceException('实名认证失败');
            }
            Redis::set('registerCode_'.$phone,null);
            $insert['id'] = getSnowFlakeId();
            //处理邀请码
            if ($inviteCode){
                $inviteCodeModel = Sale::query()->where('code',$inviteCode)->first();
                if (!$inviteCodeModel || empty(data_get($inviteCodeModel,'code'))){
                    throw new ServiceException('邀请码无效');
                }
                $insert['invite_code'] = $inviteCode;
            }
            DB::commit();
            return Customer::query()->insert($insert);
        } catch (ServiceException $e){
            DB::rollBack();
            throw $e;
        } catch (\Exception $e){
            DB::rollBack();
            throw new ServiceException($e->getMessage());
        }
    }

    public function getRegisterCode($phone){
        if (!$phone){
            throw new ServiceException('请填写手机号');
        }
        if(!isPhone($phone)){
            throw new ServiceException('手机号格式不正确');
        }
        if (Customer::query()->where('phone',$phone)->exists()){
            throw new ServiceException('当前手机号已经注册');
        }
        try{
            $code = Random::generate(6,'0-9');//验证码
            $send = false;
            if (config('app.env') == '204'){ //SmsService $smsService;
                $send = $this->smsService->sendMessage($phone,$code,config('Sms.xmMobileRegister'));
            }
            Redis::setex('registerCode_'.$phone,300,$code); //保存到缓存中
            Log::info("$phone : $code , send : $send");
            return true;
        }catch(\Exception $e){
            return ResponseUtil::error($e->getMessage());
        }
    }

    /**
     * @param $phone
     * @param $password
     * @return \Illuminate\Database\Eloquent\HigherOrderBuilderProxy|mixed
     * @throws int|\Exception
     */
    public function companyLogin($phone,$password){ //官方登录
        DB::beginTransaction();
        if (!$phone || !$password){
            throw new \Exception('账号和密码不允许为空');
        }
        $customer = Customer::query()->where('phone',$phone)->first();
        if (!$customer){
            throw new \Exception('账号或密码错误');
        }
        if (Crypt::decryptString($customer->password) != $password){
            throw new \Exception('账号或密码错误');
        }

        DB::commit();
        //判断是否是模拟登录
        if ($simulationLogin = SimulationLogin::query()->where('target_id',$customer->id)->first()) {
            return (int)$simulationLogin->from_id;
        }
        return $customer->id;
    }

    /**
     * @param $accessToken
     * @return \Illuminate\Database\Eloquent\HigherOrderBuilderProxy|int|mixed
     * @throws int|\Exception
     */
    public function douyinLogin($accessToken){ //抖音登录
        $data = $this->DouyinService->login($accessToken);
        $sdk_open_id = data_get($data,'sdk_open_id'); //用户唯一标识
        // $age_type = data_get($data,'age_type'); // -1 未实名, 8 0-8岁 ; 16 8-16岁 18 16-18 100 100 18~
        $customer = Customer::query()->where('channel_uuid',$sdk_open_id)->first();
        $customerId = null;
        if ($customer) {
            $customerId = $customer->id;
        } else {
            $customerId = getSnowFlakeId();
            Customer::query()->insertGetId([ //新增用户数据
                'id'=>$customerId,
                'channel_uuid'=>$sdk_open_id,
                'channel_type'=>2,
                'created_at'=>date("Y-m-d H:i:s"),
            ]);
        }

        if (SimulationLogin::query()->where('from_id',$customerId)->exists()){ //被模拟登录了
            throw new ServiceException('官方技术正在查看你的账号,请稍后再试');
        }
        return $customerId;
    }

    public function yiyouLogin($accessToken) //易游登录
    {
        $arr = explode("_",$accessToken);
        $memId = $arr[0];
        $customer = Customer::query()->where('channel_uuid',$memId)->first();
        if ($customer) {
            $customerId = $customer->id;
        } else {
            $customerId = getSnowFlakeId();
            $data = $this->yiyouService->login($accessToken);
            $menId = data_get($data,'mem_id');
            if ($menId){
                Customer::query()->insertGetId([ //新增用户数据
                    'id'=>$customerId,
                    'channel_uuid'=>$memId,
                    'channel_type'=>3,
                    'created_at'=>date("Y-m-d H:i:s"),
                ]);
            } else {
                throw new ServiceException('登录失败');
            }
        }
        if (SimulationLogin::query()->where('from_id',$customerId)->exists()){ //被模拟登录了
            throw new ServiceException('官方技术正在查看你的账号,请稍后再试');
        }
        return $customerId;
    }


    public function customeractive(CustomerDTO $customerDTO)
    {
        $customerIds = $customerDTO->getCustomerIds(); // 角色列表
        $page = $customerDTO->getPage();
        $pageSize = $customerDTO->getLimit();
        $customerId = $customerDTO->getCustomerId();
        $createDateTimeBegin = $customerDTO->getCreateDateBegin();
        $createDateTimeEnd = $customerDTO->getCreateDateEnd();
        $platform = $customerDTO->getPlatform();

        $model = LoginLogs::query();

        if ($customerId) {
            $model->where('id', $customerId);
        }

        if ($customerIds) {
            $customerIdlists = explode("\n", $customerIds);
            $model->whereIn('id', $customerIdlists);
        }

        // 时间范围查询
        if ($createDateTimeBegin) {
            $model->where('logindate', '>=', $createDateTimeBegin);
        }

        if ($createDateTimeEnd) {
            $model->where('logindate', '<=', $createDateTimeEnd);
        }

        // 平台类型查询
        if ($platform) {
            $model->where('type', $platform);
        }
        $model->where('serverid', '>=', 0);

        return $model->orderByDesc('id')->paginate($pageSize, '*', 'page', $page);
    }

    /**
     * 获取DAU、WAU、MAU统计
     */
    public function getActiveUserStats(CustomerDTO $customerDTO)
    {
        $createDateTimeBegin = $customerDTO->getCreateDateTimeBegin();
        $createDateTimeEnd = $customerDTO->getCreateDateTimeEnd();
        $gameArea = $customerDTO->getGameArea();
        $platform = $customerDTO->getPlatform();

        // 如果没有指定日期范围，默认查询最近30天
        if (!$createDateTimeBegin || !$createDateTimeEnd) {
            $createDateTimeEnd = now()->format('Y-m-d');
            $createDateTimeBegin = now()->subDays(30)->format('Y-m-d');
        }

        $startDate = \Carbon\Carbon::parse($createDateTimeBegin);
        $endDate = \Carbon\Carbon::parse($createDateTimeEnd);

        $result = [];

        // 遍历每一天
        for ($date = $startDate->copy(); $date->lte($endDate); $date->addDay()) {
            $dateString = $date->format('Y-m-d');
            $dayStart = $date->startOfDay()->format('Y-m-d H:i:s');
            $dayEnd = $date->endOfDay()->format('Y-m-d H:i:s');

            // 构建查询条件
            $query = LoginLogs::query()
                ->whereBetween('logindate', [$dayStart, $dayEnd])
                ->where('serverid', '>=', 0);


            // 如果有游戏区域筛选
            if ($gameArea) {
                $query->where('serverid', $gameArea);
            }
            if ($platform) {
                $query->where('type', $platform);
            }

            // DAU: 当天登录过游戏的玩家数量
            $dau = $query->distinct('customer_id')->count('customer_id');

            // WAU: 自当天起往前推7天内登录过游戏的玩家数量，按玩家ID去重
            $weekStart = $date->copy()->subDays(6)->startOfDay()->format('Y-m-d H:i:s');
            $wauQuery = LoginLogs::query()
                ->whereBetween('logindate', [$weekStart, $dayEnd])
                ->where('serverid', '>=', 0);

            if ($gameArea) {
                $wauQuery->where('serverid', $gameArea);
            }
            $wau = $wauQuery->distinct('customer_id')->count('customer_id');

            // MAU: 自当天起往前推30天内登录过游戏的玩家数量，按玩家ID去重
            $monthStart = $date->copy()->subDays(29)->startOfDay()->format('Y-m-d H:i:s');
            $mauQuery = LoginLogs::query()
                ->whereBetween('logindate', [$monthStart, $dayEnd])
                ->where('serverid', '>=', 0);

            if ($gameArea) {
                $mauQuery->where('serverid', $gameArea);
            }
            $mau = $mauQuery->distinct('customer_id')->count('customer_id');

            $result[] = [
                '日期' => $dateString,
                'DAU' => $dau,
                'WAU' => $wau,
                'MAU' => $mau,
            ];
        }

        return $result;
    }

    /**
     * 获取游戏次数统计
     */
    public function getGameTimesStats(CustomerDTO $customerDTO)
    {
        $createDateTimeBegin = $customerDTO->getCreateDateTimeBegin();
        $createDateTimeEnd = $customerDTO->getCreateDateTimeEnd();
        $gameArea = $customerDTO->getGameArea();
        $platform = $customerDTO->getPlatform();

        // 如果没有指定日期范围，默认查询最近60天
        if (!$createDateTimeBegin || !$createDateTimeEnd) {
            $createDateTimeEnd = now()->format('Y-m-d');
            $createDateTimeBegin = now()->subDays(60)->format('Y-m-d');
        }

        $startDate = \Carbon\Carbon::parse($createDateTimeBegin);
        $endDate = \Carbon\Carbon::parse($createDateTimeEnd);

        $dayStart = $startDate->startOfDay()->format('Y-m-d H:i:s');
        $dayEnd = $endDate->endOfDay()->format('Y-m-d H:i:s');

        // 构建查询条件
        $query = LoginLogs::query()
            ->whereBetween('logindate', [$dayStart, $dayEnd])
            ->where('serverid', '>=', 0);

        // 如果有游戏区域筛选
        if ($gameArea) {
            $query->where('serverid', $gameArea);
        }
        if ($platform) {
            $query->where('type', $platform);
        }
        // 统计每个用户的游戏次数
        $userGameTimes = $query->selectRaw('customer_id, COUNT(*) as game_times')
            ->groupBy('customer_id')
            ->get();

        // 按游戏次数分组统计
        $gameTimesDistribution = [
            '1' => 0,
            '2-3' => 0,
            '4-7' => 0,
            '8-15' => 0,
            '15+' => 0,
        ];

        foreach ($userGameTimes as $user) {
            $times = $user->game_times;
            if ($times == 1) {
                $gameTimesDistribution['1']++;
            } elseif ($times >= 2 && $times <= 3) {
                $gameTimesDistribution['2-3']++;
            } elseif ($times >= 4 && $times <= 7) {
                $gameTimesDistribution['4-7']++;
            } elseif ($times >= 8 && $times <= 15) {
                $gameTimesDistribution['8-15']++;
            } elseif ($times > 15) {
                $gameTimesDistribution['15+']++;
            }
        }

        // 转换为前端需要的格式
        $result = [];
        foreach ($gameTimesDistribution as $range => $count) {
            $result[] = [
                '启动游戏次数' => $range,
                '人数' => $count,
            ];
        }

        return $result;
    }

    /**
     * 获取游戏次数统计
     */
    public function getGameTimes(CustomerDTO $customerDTO)
    {
        $createDateTimeBegin = $customerDTO->getCreateDateTimeBegin();
        $createDateTimeEnd = $customerDTO->getCreateDateTimeEnd();
        $gameArea = $customerDTO->getGameArea();
        $platform = $customerDTO->getPlatform();

        // 如果没有指定日期范围，默认查询最近60天
        if (!$createDateTimeBegin || !$createDateTimeEnd) {
            $createDateTimeEnd = now()->format('Y-m-d');
            $createDateTimeBegin = now()->subDays(60)->format('Y-m-d');
        }

        $startDate = \Carbon\Carbon::parse($createDateTimeBegin);
        $endDate = \Carbon\Carbon::parse($createDateTimeEnd);

        $dayStart = $startDate->startOfDay()->format('Y-m-d H:i:s');
        $dayEnd = $endDate->endOfDay()->format('Y-m-d H:i:s');

        // 构建查询条件
        $query = Customer::query();

        // 按游戏时长分组统计
        $gameTimesDistribution = [
            '1' => 0,    // 1到2天
            '2' => 0,    // 2到3天
            '3' => 0,    // 3到4天
            '4-7' => 0,  // 4到7天
            '8-15' => 0, // 8到15天
            '16-30' => 0,// 16到30天
            '31+' => 0,  // 31天及以上
        ];

        // 获取所有符合条件的客户
        $customers = $query->get();
        $totalCustomers = $customers->count(); // 总客户人数

        // 统计游戏时长
        foreach ($customers as $customer) {
            $gametimes = $customer->gametimes;

            if ($gametimes < 2) {
                $gameTimesDistribution['1']++;
            } elseif ($gametimes >1 && $gametimes < 3) {
                $gameTimesDistribution['2']++;
            } elseif ($gametimes >2 && $gametimes < 4) {
                $gameTimesDistribution['3']++;
            } elseif ($gametimes >= 4 && $gametimes <= 7) {
                $gameTimesDistribution['4-7']++;
            } elseif ($gametimes >= 8 && $gametimes <= 15) {
                $gameTimesDistribution['8-15']++;
            } elseif ($gametimes >= 16 && $gametimes <= 30) {
                $gameTimesDistribution['16-30']++;
            } elseif ($gametimes > 30) {
                $gameTimesDistribution['31+']++;
            }
        }
        // 转换为前端需要的格式
        $result = [];
        foreach ($gameTimesDistribution as $range => $count) {
            $percentage = $totalCustomers > 0 ? ($count / $totalCustomers) * 100 : 0; // 计算占比

            $result[] = [
                '游戏时长' => $range,
                '人数' => $count,
                '占比' => round($percentage, 2)// 保留两位小数

            ];
        }
        // 返回统计结果
        return $result;
    }

    /**
     * 获取首页总览统计数据
     */
    public function getDashboardStats(CustomerDTO $customerDTO)
    {
        $gameArea = $customerDTO->getGameArea();

        // 设置全局游戏区域
        global $gameArea;
        $gameArea = $gameArea ?: 0;

        // 今日时间范围
        $todayStart = now()->startOfDay()->format('Y-m-d H:i:s');
        $todayEnd = now()->endOfDay()->format('Y-m-d H:i:s');
        $todayStartTimestamp = strtotime($todayStart);
        $todayEndTimestamp = strtotime($todayEnd);

        // 项目数据统计
        $totalCustomers = Customer::query()->count(); // 总注册玩家

        $totalPayAmount = \App\Models\Game\PayOrder::query()
            ->where('status', 1)
            ->sum('fee'); // 总付费金额

        $totalPayCustomers = \App\Models\Game\PayOrder::query()
            ->where('status', 1)
            ->where('push_status', 1)
            ->distinct('customer_id')
            ->count('customer_id'); // 总付费玩家数

        $avgPayRate = $totalCustomers > 0 ? ($totalPayCustomers / $totalCustomers) * 100 : 0; // 平均付费率
        $avgARPU = $totalCustomers > 0 ? $totalPayAmount / $totalCustomers : 0; // 平均ARPU
        $avgARPPU = $totalPayCustomers > 0 ? $totalPayAmount / $totalPayCustomers : 0; // 平均ARPPU

        // 运营时间（从第一个用户注册开始计算）
        $firstCustomer = Customer::query()->orderBy('created_at')->first();
        $operationDays = $firstCustomer ? now()->diffInDays($firstCustomer->created_at) : 0;

        // 今日数据统计
        $todayNewCustomers = Customer::query()
            ->whereBetween('created_at', [$todayStart, $todayEnd])
            ->count(); // 今日新增玩家

        $todayPayAmount = \App\Models\Game\PayOrder::query()
            ->where('status', 1)
            ->whereBetween('created_at', [$todayStart, $todayEnd])
            ->sum('fee'); // 今日充值金额

        $todayPayCustomers = \App\Models\Game\PayOrder::query()
            ->where('status', 1)
            ->whereBetween('created_at', [$todayStart, $todayEnd])
            ->distinct('customer_id')
            ->count('customer_id'); // 今日付费人数

        $todayPayOrders = \App\Models\Game\PayOrder::query()
            ->where('status', 1)
            ->whereBetween('created_at', [$todayStart, $todayEnd])
            ->count(); // 今日付费笔数

        $todayPayRate = $todayNewCustomers > 0 ? ($todayPayCustomers / $todayNewCustomers) * 100 : 0; // 今日付费率
        $todayARPU = $todayNewCustomers > 0 ? $todayPayAmount / $todayNewCustomers : 0; // 今日ARPU
        $todayARPPU = $todayPayCustomers > 0 ? $todayPayAmount / $todayPayCustomers : 0; // 今日ARPPU

        // 实时在线玩家数量（从登录日志获取）
        $onlinePlayers = 0;

        // 分服数据统计
        $serverData = [];
        $servers = \App\Models\Game\Server::query()->where('mysql_game_data_can_use',1)->where('status',1)->get();

        foreach ($servers as $server) {
            // 设置当前服务器连接
            global $gameArea;
            $gameArea = $server->server_id;

            // 重新初始化UserMember模型以使用正确的数据库连接
            $userMemberModel = new \App\Models\Game\UserMember();

            $serverTotalPlayers = $userMemberModel->count(); // 服务器总玩家数
            $startTime=$server->created_at;
            $serverPayAmount = \App\Models\Game\PayOrder::query()
                ->where('status', 1)
                ->where('game_area', $server->server_id)
                ->where('created_at','>',$startTime)
                ->sum('fee'); // 服务器付费总量

            try {
            $serverTodayNewPlayers = $userMemberModel
                ->whereBetween('createtime', [$todayStartTimestamp, $todayEndTimestamp])
                ->count(); // 今日新增玩家
            } catch (\Exception $e) {
                // 记录错误并跳过当前 serverId
                MyLog::info('连接失败，跳过服务器ID: ' . json_encode($gameArea) . ' 错误信息: ' . $e->getMessage());
                continue; // 跳过到下一个 serverId
            }
            $serverTodayPayCustomers = \App\Models\Game\PayOrder::query()
                ->where('status', 1)
                ->where('game_area', $server->server_id)
                ->whereBetween('created_at', [$todayStart, $todayEnd])
                ->distinct('customer_id')
                ->count('customer_id'); // 今日付费人数


            $serverALLPayCustomers = \App\Models\Game\PayOrder::query()
                ->where('status', 1)
                ->where('game_area', $server->server_id)
                ->distinct('customer_id')
                ->count('customer_id'); // 总付费人数

                $serverTodaycustomerIds= $userMemberModel->select('openid')
                ->whereBetween('createtime', [$todayStartTimestamp, $todayEndTimestamp])
                ->get()->toArray();

            $serverTodayNewPayCustomers = \App\Models\Game\PayOrder::query()
                ->where('status', 1)
                ->where('game_area', $server->id)
                ->whereBetween('created_at', [$todayStart, $todayEnd])
                ->whereIn('customer_id', $serverTodaycustomerIds)
                ->distinct('customer_id')
                ->count('customer_id'); // 新增付费玩家

            $serverTodayPayOrders = \App\Models\Game\PayOrder::query()
                ->where('status', 1)
                ->where('game_area', $server->server_id)
                ->whereBetween('created_at', [$todayStart, $todayEnd])
                ->count(); // 今日付费笔数

            $serverPayRate = $serverTotalPlayers > 0 ? ($serverALLPayCustomers / $serverTotalPlayers) * 100 : 0; // 付费率
            $serverARPU = $serverTotalPlayers > 0 ? $serverPayAmount / $serverTotalPlayers : 0; // ARPU
            $serverARPPU = $serverTodayPayCustomers > 0 ? $serverPayAmount / $serverALLPayCustomers : 0; // ARPPU

            // 开服天数
            $serverStartDate = \Carbon\Carbon::parse($server->start_time ?? $server->created_at);
            $serverDays = now()->diffInDays($serverStartDate);

            $serverData[] = [
                '服务器' => $server->name ?? "服务器{$server->id}",
                '开服时间' => $serverStartDate->format('Y-m-d'),
                '开服天数' => $serverDays,
                '总玩家数' => $serverTotalPlayers,
                '付费总量' => number_format($serverPayAmount, 2),
                '今日新增玩家' => $serverTodayNewPlayers,
                '今日付费人数' => $serverTodayPayCustomers,
                '总付费玩家' => $serverALLPayCustomers,
                '新增付费玩家' => $serverTodayNewPayCustomers,
                '今日付费笔数' => $serverTodayPayOrders,
                '付费率' => number_format($serverPayRate, 2) . '%',
                'ARPU' => number_format($serverARPU, 2),
                'ARPPU' => number_format($serverARPPU, 2)
            ];


                $onLineModel = new OnLine();
                $onLineModel->setConnection('function_' . $gameArea);

                // 尝试获取第一个在线用户记录
                $result = $onLineModel->paginate()->first();

                MyLog::info('当前组装服务器ID: ' . json_encode($gameArea));

            if ($result) {
                $onlinePlayers += $result->onlines; // 累加在线玩家数量
            }

        }

        return [
            'projectData' => [
                ['label' => '运营时间[天]', 'value' => $operationDays],
                ['label' => '总注册玩家', 'value' => number_format($totalCustomers)],
                ['label' => '总付费[元]', 'value' => number_format($totalPayAmount, 2)],
                ['label' => '平均付费率', 'value' => number_format($avgPayRate, 2) . '%'],
                ['label' => '平均ARPU', 'value' => number_format($avgARPU, 2)],
                ['label' => '平均ARPPU', 'value' => number_format($avgARPPU, 2)]
            ],
            'todayData' => [
                ['label' => '实时在线玩家数据量', 'value' => number_format($onlinePlayers)],
                ['label' => '今日新增玩家', 'value' => number_format($todayNewCustomers)],
                ['label' => '新增付费玩家', 'value' => number_format($todayPayCustomers)],
                ['label' => 'ARPPU', 'value' => number_format($todayARPPU, 2)],
                ['label' => '今日充值[元]', 'value' => number_format($todayPayAmount, 2)],
                ['label' => '付费率', 'value' => number_format($todayPayRate, 2) . '%'],
                ['label' => '今日新增付费笔数', 'value' => number_format($todayPayOrders)],
                ['label' => 'ARPU', 'value' => number_format($todayARPU, 2)]
            ],
            'serverData' => $serverData
        ];
    }

    /**
     * 导出游戏进度数据
     *
     * @param string $gameArea 服务器ID
     * @param string $type 数据类型 (level/task)
     * @param string $exportDate 导出日期
     * @return array 导出数据
     */
    public function exportProgressData($gameArea, $type, $exportDate)
    {
        global $gameArea;
        $gameArea = $gameArea;

        switch ($type) {
            case 'level':
                return $this->exportLevelDistribution($gameArea, $exportDate);
            case 'task':
                return $this->exportTaskDistribution($gameArea, $exportDate);
            default:
                throw new \Exception('不支持的数据类型');
        }
    }

    /**
     * 导出等级分布数据
     */
    private function exportLevelDistribution($gameArea, $exportDate)
    {
        // 从数据库查询等级分布数据
        $data = DB::table('userlevelelogs')
            ->where('server_id', $gameArea)
            ->whereDate('created_at', $exportDate)
            ->orderBy('level')
            ->orderBy('created_at')
            ->get()
            ->map(function ($item) {
                return [
                    '服务器ID' => $item->server_id,
                    '统计时间' => $item->created_at,
                    '等级' => $item->level,
                    '人数' => $item->counts,
                    '占比(%)' => $item->percentage,
                    '平均滞留时间(天)' => $item->avgtime
                ];
            })
            ->toArray();

        return [
            'title' => '等级分布数据',
            'filename' => 'level_distribution_' . $gameArea . '_' . $exportDate . '.xlsx',
            'data' => $data
        ];
    }

    /**
     * 导出任务分布数据
     */
    private function exportTaskDistribution($gameArea, $exportDate)
    {
        // 从数据库查询任务分布数据
        $data = DB::table('usertasklogs')
            ->where('server_id', $gameArea)
            ->whereDate('created_at', $exportDate)
            ->orderBy('taskid')
            ->orderBy('created_at')
            ->get()
            ->map(function ($item) {
                return [
                    '服务器ID' => $item->server_id,
                    '统计时间' => $item->created_at,
                    '任务ID' => $item->taskid,
                    '任务名称' => $item->taskname,
                    '已接未完成' => $item->activeType1,
                    '未完成占比(%)' => $item->activeType1per,
                    '已提交已完成' => $item->activeType2,
                    '完成占比(%)' => $item->activeType2per,
                    '平均滞留时间(天)' => $item->avgtime
                ];
            })
            ->toArray();

        return [
            'title' => '主线任务分布数据',
            'filename' => 'task_distribution_' . $gameArea . '_' . $exportDate . '.xlsx',
            'data' => $data
        ];
    }
}
